package cn.topkinson.dubbo.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author 黄子濠
 * @date 2020/8/30 22:13
 */
@Activate(group = {CommonConstants.CONSUMER})
public class TPFilter implements Filter {

    private static volatile AtomicInteger count = new AtomicInteger(0);

    TreeMap<Integer, String> treeMapA = new TreeMap<>(Comparator.naturalOrder());

    private volatile AtomicBoolean start = new AtomicBoolean(false);

    private final Object OBJECT = new Object();

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

        synchronized (OBJECT){
            if (!start.get()){
                start();
            }
        }
        long startTime = System.currentTimeMillis();
        String methodName = invocation.getMethodName();
        try {
            // 执行方法
            return  invoker.invoke(invocation);
        } finally {
            long endTime = System.currentTimeMillis();
            String v = methodName+"_"+endTime+"_"+(endTime-startTime);
            treeMapA.put(count.incrementAndGet(),v);
        }
    }

    public void start() {
        start.set(true);
        System.out.println("启动定时任务。。");
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("===========开始统计============");
                //60秒前
                long now_sub60 = System.currentTimeMillis() - 60*1000;

                TreeMap<Integer, String> treeMap = (TreeMap<Integer, String>)treeMapA.clone();
                //System.out.println("treeMap.size():"+treeMap.size());
                //过滤掉60秒前的数据，并汇总调用时间
                List<String> vListA = treeMap.values().stream().filter(v -> {
                    Long callTime = Long.valueOf(v.split("_")[1]);
                    return callTime > now_sub60 && "methodA".equals(v.split("_")[0]);
                }).collect(Collectors.toList());
                List<String> vListB = treeMap.values().stream().filter(v -> {
                    Long callTime = Long.valueOf(v.split("_")[1]);
                    return callTime > now_sub60 && "methodB".equals(v.split("_")[0]);
                }).collect(Collectors.toList());
                List<String> vListC = treeMap.values().stream().filter(v -> {
                    Long callTime = Long.valueOf(v.split("_")[1]);
                    return callTime > now_sub60 && "methodC".equals(v.split("_")[0]);
                }).collect(Collectors.toList());
                Long totalA = vListA.stream().mapToLong(o->Long.valueOf(o.split("_")[2])).sum();
                Long totalB = vListB.stream().mapToLong(o->Long.valueOf(o.split("_")[2])).sum();
                Long totalC = vListC.stream().mapToLong(o->Long.valueOf(o.split("_")[2])).sum();
                System.out.println("totalA:"+totalA+"_totalB:"+totalB+"_totalC:"+totalC);
                //计算TP90和TP99
                Double idx90A= Math.ceil((double)totalA*90/100);
                Double idx99A= Math.ceil((double)totalA*99/100);
                Double idx90B= Math.ceil((double)totalB*90/100);
                Double idx99B= Math.ceil((double)totalB*99/100);
                Double idx90C= Math.ceil((double)totalC*90/100);
                Double idx99C= Math.ceil((double)totalC*99/100);

                AtomicReference<Integer> idxA= new AtomicReference<>(0);
                AtomicReference<Integer> idxB= new AtomicReference<>(0);
                AtomicReference<Integer> idxC= new AtomicReference<>(0);
                TreeMap<Integer, Long> transMapA = new TreeMap<>(Comparator.naturalOrder());
                TreeMap<Integer, Long> transMapB = new TreeMap<>(Comparator.naturalOrder());
                TreeMap<Integer, Long> transMapC = new TreeMap<>(Comparator.naturalOrder());
                vListA.forEach(o->{
                    Integer value = Integer.valueOf(o.split("_")[2]);
                    transMapA.put(idxA.get(),Long.valueOf(value));
                    idxA.updateAndGet(v -> v + value);
                });
                vListB.forEach(o->{
                    Integer value = Integer.valueOf(o.split("_")[2]);
                    transMapB.put(idxB.get(),Long.valueOf(value));
                    idxB.updateAndGet(v -> v + value);
                });
                vListC.forEach(o->{
                    Integer value = Integer.valueOf(o.split("_")[2]);
                    transMapC.put(idxC.get(),Long.valueOf(value));
                    idxC.updateAndGet(v -> v + value);
                });

                Map.Entry<Integer, Long> idx90EntryA = transMapA.floorEntry(idx90A.intValue());
                Map.Entry<Integer, Long> idx99EntryA = transMapA.floorEntry(idx99A.intValue());
                Map.Entry<Integer, Long> idx90EntryB = transMapB.floorEntry(idx90B.intValue());
                Map.Entry<Integer, Long> idx99EntryB = transMapB.floorEntry(idx99B.intValue());
                Map.Entry<Integer, Long> idx90EntryC = transMapC.floorEntry(idx90C.intValue());
                Map.Entry<Integer, Long> idx99EntryC = transMapC.floorEntry(idx99C.intValue());

                Long TP90A=idx90EntryA.getValue();
                Long TP99A=idx99EntryA.getValue();
                Long TP90B=idx90EntryB.getValue();
                Long TP99B=idx99EntryB.getValue();
                Long TP90C=idx90EntryC.getValue();
                Long TP99C=idx99EntryC.getValue();

                System.out.println("A:TP90:"+TP90A+", TP99:"+TP99A);
                System.out.println("B:TP90:"+TP90B+", TP99:"+TP99B);
                System.out.println("C:TP90:"+TP90C+", TP99:"+TP99C);
                System.out.println("===========统计结束============");
            }
        }, 5000,5000);
    }
}